/*******************************************************************************
** 文件名称：soft_timer.c
** 文件作用：软件定时器源文件
** 编写作者：Tom Free 付瑞彪
** 编写时间：2018-11-03
** 文件备注：
**
**
** 更新记录：
**          2018-11-03 -> 创建文件                          <Tom Free 付瑞彪>
**
**
**       Copyright (c) 深圳市三派智能科技有限公司 All Rights Reserved
**
**       1 Tab == 4 Spaces     UTF-8     ANSI C Language(C99)
*******************************************************************************/

#include "soft_timer.h"

/* 临界段处理方法定义 */
#define SOFT_TIMER_ENTER_CRITICAL()     asm("cli")  /* 失能中断 */
#define SOFT_TIMER_EXIT_CRITICAL()      asm("sei")  /* 使能中断 */

/* 软件定时器结构 */
typedef struct
{
    GM_BOOL      isActive;  /* 是否处于激活状态 */
    GM_BOOL      isTimeout; /* 时间是否溢出 */
    GM_BOOL      isPeriod;  /* 是否周期执行 */
    GM_U16       interval;  /* 计时周期 */
    GM_U16       count;     /* 计数器 */
    GM_CALLBACK* callback;  /* 回调函数 */
} SOFT_TIMER;

/* 软件定时器表 */
static SOFT_TIMER SoftTimer[SOFT_TIMER_TOTAL];

/*******************************************************************************
** 函数名称：SoftTimer_Init
** 函数作用：软件定时器初始化
** 输入参数：无
** 输出参数：无
** 使用范例：SoftTimer_Init();
** 函数备注：
*******************************************************************************/
void SoftTimer_Init()
{
    GM_U8 i = 0;
    SOFT_TIMER_ENTER_CRITICAL();
    for (i = 0; i < SOFT_TIMER_TOTAL;i++)
    {
        SoftTimer[i].isActive = GM_FALSE;
        SoftTimer[i].isPeriod = GM_FALSE;
        SoftTimer[i].isTimeout = GM_FALSE;
        SoftTimer[i].interval = 0;
        SoftTimer[i].count = 0;
        SoftTimer[i].callback = GM_NULL;
    }
    SOFT_TIMER_EXIT_CRITICAL();
}

/*******************************************************************************
** 函数名称：SoftTimer_Setup
** 函数作用：配置某个软件定时器
** 输入参数：index - 软件定时器ID
**           interval - 定时时间
**           isPeriod - 是否周期执行
**           cb - 周期执行时的回调函数
** 输出参数：无
** 使用范例：SoftTimer_Setup(0, 100, GM_FALSE, GM_NULL);
** 函数备注：此函数不会启动定时器运行
*******************************************************************************/
void SoftTimer_Setup(GM_U8 index, GM_U16 interval, GM_BOOL isPeriod, GM_CALLBACK *cb)
{
    SOFT_TIMER_ENTER_CRITICAL();

    SoftTimer[index].isActive = GM_FALSE;
    SoftTimer[index].interval = interval;
    SoftTimer[index].isPeriod = isPeriod;
    SoftTimer[index].isTimeout = GM_FALSE;
    SoftTimer[index].count = interval;
    SoftTimer[index].callback = cb;

    SOFT_TIMER_EXIT_CRITICAL();
}

/*******************************************************************************
** 函数名称：SoftTimer_Start
** 函数作用：启动某个软件定时器
** 输入参数：
** 输出参数：无
** 使用范例：SoftTimer_Start(0, 100, GM_FALSE, GM_NULL);
** 函数备注：
*******************************************************************************/
void SoftTimer_Start(GM_U8 index)
{
    SOFT_TIMER_ENTER_CRITICAL();
    SoftTimer[index].isActive = GM_TRUE;
    SOFT_TIMER_EXIT_CRITICAL();
}

/*******************************************************************************
** 函数名称：SoftTimer_Stop
** 函数作用：停止某个软件定时器
** 输入参数：index - 软件定时器ID
** 输出参数：无
** 使用范例：SoftTimer_Stop(0);
** 函数备注：
*******************************************************************************/
void SoftTimer_Stop(GM_U8 index)
{
    SOFT_TIMER_ENTER_CRITICAL();

    SoftTimer[index].isActive  = GM_FALSE;
    SoftTimer[index].isTimeout = GM_FALSE;
    SoftTimer[index].count = SoftTimer[index].interval;

    SOFT_TIMER_EXIT_CRITICAL();
}

/*******************************************************************************
** 函数名称：SoftTimer_StopAll
** 函数作用：停止全部软件定时器
** 输入参数：无
** 输出参数：无
** 使用范例：SoftTimer_StopAll();
** 函数备注：
*******************************************************************************/
void SoftTimer_StopAll()
{
    GM_U8 i = 0;
    SOFT_TIMER_ENTER_CRITICAL();

    for (i = 0; i < SOFT_TIMER_TOTAL; i++)
    {
        SoftTimer[i].isActive  = GM_FALSE;
        SoftTimer[i].isTimeout = GM_FALSE;
        SoftTimer[i].count = SoftTimer[i].interval;
    }

    SOFT_TIMER_EXIT_CRITICAL();
}

/*******************************************************************************
** 函数名称：SoftTimer_ClearCount
** 函数作用：清除一个定时器计数值，即复位
** 输入参数：index - 软件定时器ID
** 输出参数：无
** 使用范例：SoftTimer_ClearCount(0);
** 函数备注：
*******************************************************************************/
void SoftTimer_Reload(GM_U8 index)
{
    SOFT_TIMER_ENTER_CRITICAL();
    SoftTimer[index].count = SoftTimer[index].interval;
    SOFT_TIMER_EXIT_CRITICAL();
}

/*******************************************************************************
** 函数名称：SoftTimer_CheckTimeout
** 函数作用：检测某个软件定时器是否超时
** 输入参数：index - 软件定时器ID
** 输出参数：无
** 使用范例：GM_BOOL res = SoftTimer_CheckTimeout(0);
** 函数备注：
*******************************************************************************/
GM_BOOL SoftTimer_CheckTimeout(GM_U8 index)
{
    return SoftTimer[index].isTimeout;
}

/*******************************************************************************
** 函数名称：SoftTimer_ClearTimeout
** 函数作用：清除某个软件定时器超时标志
** 输入参数：index - 软件定时器ID
** 输出参数：无
** 使用范例：SoftTimer_ClearTimeout(0);
** 函数备注：
*******************************************************************************/
void SoftTimer_ClearTimeout(GM_U8 index)
{
    SOFT_TIMER_ENTER_CRITICAL();
    SoftTimer[index].isTimeout = GM_FALSE;
    SOFT_TIMER_EXIT_CRITICAL();
}

/*******************************************************************************
** 函数名称：SoftTimer_InterruptHandle
** 函数作用：软件定时器的中断处理
** 输入参数：无
** 输出参数：无
** 使用范例：SoftTimer_InterruptHandle();
** 函数备注：此函数须在中断中调用
*******************************************************************************/
void SoftTimer_TicksHandle()
{
    GM_U8 i = 0;

    SOFT_TIMER_ENTER_CRITICAL();

    /* 遍历所有定时器 */
    for (i = 0; i < SOFT_TIMER_TOTAL; i++)
    {
        if ((SoftTimer[i].isActive == GM_TRUE) && (--SoftTimer[i].count == 0))
        {
            /* 溢出 */
            SoftTimer[i].isTimeout = GM_TRUE;
            /* 重载 */
            SoftTimer[i].count = SoftTimer[i].interval;
            /* 关闭定时器 */
            if (SoftTimer[i].isPeriod == 0)
            {
                SoftTimer[i].isActive = GM_FALSE;
            }
        }
    }

    SOFT_TIMER_EXIT_CRITICAL();
}

/*******************************************************************************
** 函数名称：SoftTimer_EventHandle
** 函数作用：软件定时器的事件处理
** 输入参数：无
** 输出参数：无
** 使用范例：SoftTimer_EventHandle();
** 函数备注：
*******************************************************************************/
void SoftTimer_EventHandler()
{
    GM_U8 i = 0;

    /* 进入临界段 */
    SOFT_TIMER_ENTER_CRITICAL();

    /* 遍历所有定时器 */
    for (i = 0; i < SOFT_TIMER_TOTAL; i++)
    {
        if ((SoftTimer[i].isTimeout == GM_TRUE) &&
            (SoftTimer[i].callback != GM_NULL))
        {
            /* 有回调函数就清溢出标志并执行回调，无则退出，啥都不干，让用户自己处理 */
            SoftTimer[i].isTimeout = GM_FALSE;
            SoftTimer[i].callback(&SoftTimer[i], 0);
        }
    }

    SOFT_TIMER_EXIT_CRITICAL();
}
